﻿using NodeBasedSkillEditor.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace NodeBasedSkillEditor.View
{
    public partial class NodeControl : UserControl
    {
        public string NodeName {
            get { return (string)GetValue(NodeNameProperty); }
            set { SetValue(NodeNameProperty, value); }
        }
        public static readonly DependencyProperty NodeNameProperty =
            DependencyProperty.Register("NodeName", typeof(string), typeof(NodeControl),
                new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public bool IsSelected {
            get { return (bool)GetValue(IsSelectedProperty); }
            set { SetValue(IsSelectedProperty, value); }
        }
        public static readonly DependencyProperty IsSelectedProperty =
            DependencyProperty.Register("IsSelected", typeof(bool), typeof(NodeControl),
                new FrameworkPropertyMetadata(
                    false,
                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                    OnIsSelectedPropertyChanged));
        static void OnIsSelectedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var s = sender as NodeControl;
            s.UpdateTitleAndOutlineColor();
        }

        public bool IsEntry {
            get { return (bool)GetValue(IsEntryProperty); }
            set { SetValue(IsEntryProperty, value); }
        }
        public static readonly DependencyProperty IsEntryProperty =
            DependencyProperty.Register("IsEntry", typeof(bool), typeof(NodeControl),
                new FrameworkPropertyMetadata(
                    false,
                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                    OnIsEntryPropertyChanged));
        static void OnIsEntryPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var s = sender as NodeControl;
            s.UpdateTitleAndOutlineColor();
        }

        public Point Position {
            get { return (Point)GetValue(PositionProperty); }
            set { SetValue(PositionProperty, value); }
        }
        public static readonly DependencyProperty PositionProperty =
            DependencyProperty.Register("Position", typeof(Point), typeof(NodeControl),
                new FrameworkPropertyMetadata(new Point(),
                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnPositionPropertyChanged));
        static void OnPositionPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var s = sender as NodeControl;
            s._translate.X = s.Position.X;
            s._translate.Y = s.Position.Y;
        }

        public string Description {
            get { return (string)GetValue(DescriptionProperty); }
            set { SetValue(DescriptionProperty, value); }
        }
        public static readonly DependencyProperty DescriptionProperty =
            DependencyProperty.Register("Description", typeof(string), typeof(NodeControl),
                new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDiscriptionPropertyChanged));
        static void OnDiscriptionPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var s = sender as NodeControl;
            if (string.IsNullOrEmpty(s.Description))
            {
                s.DescriptionVisibility = Visibility.Collapsed;
                s.BottomBorderVisibility = Visibility.Visible;
            }
            else
            {
                s.DescriptionVisibility = Visibility.Visible;
                s.BottomBorderVisibility = Visibility.Collapsed;
            }
        }

        public Visibility DescriptionVisibility {
            get { return (Visibility)GetValue(DescriptionVisibilityProperty); }
            set { SetValue(DescriptionVisibilityProperty, value); }
        }
        public static readonly DependencyProperty DescriptionVisibilityProperty =
            DependencyProperty.Register("DescriptionVisibility", typeof(Visibility), typeof(NodeControl),
                new FrameworkPropertyMetadata(Visibility.Collapsed, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public Visibility BottomBorderVisibility {
            get { return (Visibility)GetValue(BottomBorderVisibilityProperty); }
            set { SetValue(BottomBorderVisibilityProperty, value); }
        }
        public static readonly DependencyProperty BottomBorderVisibilityProperty =
            DependencyProperty.Register("BottomBorderVisibility", typeof(Visibility), typeof(NodeControl),
                new FrameworkPropertyMetadata(Visibility.Visible, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));


        public SolidColorBrush TitleBackground {
            get { return (SolidColorBrush)GetValue(TitleBackgroundProperty); }
            set { SetValue(TitleBackgroundProperty, value); }
        }
        public static readonly DependencyProperty TitleBackgroundProperty =
            DependencyProperty.Register("TitleBackground", typeof(SolidColorBrush), typeof(UserControl),
                new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public SolidColorBrush TitleForeground {
            get { return (SolidColorBrush)GetValue(TitleForegroundProperty); }
            set { SetValue(TitleForegroundProperty, value); }
        }
        public static readonly DependencyProperty TitleForegroundProperty =
            DependencyProperty.Register("TitleForeground", typeof(SolidColorBrush), typeof(UserControl),
                new FrameworkPropertyMetadata(Brushes.LightGray, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));


        public SolidColorBrush NodeColor {
            get { return (SolidColorBrush)GetValue(NodeColorProperty); }
            set { SetValue(NodeColorProperty, value); }
        }
        public static readonly DependencyProperty NodeColorProperty =
            DependencyProperty.Register("NodeColor", typeof(SolidColorBrush), typeof(NodeControl),
                new FrameworkPropertyMetadata(Brushes.DarkGray, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public Thickness OutlineThickness {
            get { return (Thickness)GetValue(OutlineThicknessProperty); }
            set { SetValue(OutlineThicknessProperty, value); }
        }
        public static readonly DependencyProperty OutlineThicknessProperty =
            DependencyProperty.Register("OutlineThickness", typeof(Thickness), typeof(NodeControl),
                new FrameworkPropertyMetadata(new Thickness(2), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));


        TranslateTransform _translate = new TranslateTransform(0, 0);
        public VM_Node ViewModel { get { return DataContext as VM_Node; } }

        bool _isMouseOver = false;

        public NodeControl()
        {
            InitializeComponent();
            var transGroup = new TransformGroup();
            transGroup.Children.Add(_translate);
            RenderTransform = transGroup;
        }

        public Rect GetBoundingBox()
        {
            return RenderTransform.TransformBounds(new Rect(RenderSize));
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            ViewModel.OnLMBDown(e);
        }

        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonUp(e);
            ViewModel.OnLMBUp(e);
        }

        protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseRightButtonDown(e);
            ViewModel.OnRMBDown(e);
        }

        protected override void OnMouseRightButtonUp(MouseButtonEventArgs e)
        {
            base.OnMouseRightButtonUp(e);
            ViewModel.OnRMBUp(e);
        }

        protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
        {
            base.OnMouseDoubleClick(e);
            ViewModel.OnDoubleClick(e);
        }

        protected override void OnMouseEnter(MouseEventArgs e)
        {
            base.OnMouseEnter(e);
            _isMouseOver = true;
            UpdateOnMouseOverChanged();
        }

        protected override void OnMouseLeave(MouseEventArgs e)
        {
            base.OnMouseLeave(e);
            _isMouseOver = false;
            UpdateOnMouseOverChanged();
        }

        private void UpdateTitleAndOutlineColor()
        {
            if (IsEntry)
            {
                BorderBrush = new SolidColorBrush(IsSelected ? Colors.LightYellow : Colors.Yellow);
                TitleForeground = new SolidColorBrush(IsSelected ? Colors.LightYellow : Colors.Yellow);
            }
            else
            {
                BorderBrush = new SolidColorBrush(IsSelected ? Colors.White : Colors.LightGray);
                TitleForeground = new SolidColorBrush(IsSelected ? Colors.White : Colors.LightGray);
            }
        }

        void UpdateOnMouseOverChanged()
        {
            TitleBackground = new SolidColorBrush(_isMouseOver ? Color.FromRgb(28, 28, 28) : Colors.Black);
        }
    }
}
